package com.blb.community.config;

import com.blb.community.handler.LoginSuccessHandler;
import com.blb.community.utils.ResponseResult;
import com.blb.community.utils.ResponseStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

/**
 * @Author 帅帅
 * @Date 2022/7/4 15:02
 * @PackageName:com.blb.community.config
 * @ClassName: SercurityConfig
 * @Description: TODO
 * @Version 1.0
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private LoginSuccessHandler loginSuccessHandler;
    /**
     * 将密码加密放到容器中
     *
     * @return
     */
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 自定义登入
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }


    @Override
    @Bean
    public UserDetailsService userDetailsServiceBean() throws Exception {
        return super.userDetailsServiceBean();
    }

    /**
     * 配置网络
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/code", "/doc.html", "/websocket/**", "/swagger-ui.html",
                        // swagger api json
                        "/v2/api-docs",
                        // 用来获取支持的动作
                        "/swagger-resources/configuration/ui",
                        // 用来获取api-docs的URI
                        "/swagger-resources",
                        // 安全选项
                        "/swagger-resources/configuration/security",
                        "/swagger-resources/**",
                        //补充路径，近期在搭建swagger接口文档时，通过浏览器控制台发现该/webjars路径下的文件被拦截，故加上此过滤条件即可。(2020-10-23)
                        "/webjars/**", "/login", "/logout")
                .permitAll()
                .anyRequest()
                .authenticated() //其他的请求需要登入
                .and()
                .formLogin()//登入配置
                //配置登入成功处理
                .successHandler(loginSuccessHandler)
                .failureHandler((req, resp, auth) -> {
                    ResponseResult.write(resp, ResponseResult.error(ResponseStatus.LOGIN_ERROR));//登入失败处理
                })
                .and()
                .exceptionHandling()
                //配置拦截未登入请求的处理器
                .authenticationEntryPoint((req, resp, auth) -> {
                    ResponseResult.write(resp, ResponseResult.error(ResponseStatus.AUTHENTICATE_ERROR));
                })
                .and()
                .rememberMe()
                .and()
                .logout()
                //配置退出成功处理器
                .logoutSuccessHandler((req, resp, auth) -> {
                    ResponseResult.write(resp, ResponseResult.ok("退出成功"));
                })
                //清楚缓存
                .clearAuthentication(true)
                .and()
                .cors()
                .configurationSource(configurationSource())
                .and()
                .csrf()
                .disable()//配置跨域
                .sessionManagement()
                //不使用session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                //把token解析过滤器添加到过滤器链中
                .addFilter(new TokenAuthenticationFilter(authenticationManager()));
    }

    @Bean
    public CorsConfigurationSource configurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedOrigins(Arrays.asList(
                "http://localhost:8082",
                "http://121.41.82.94",
                "http://xia9422.cn",
                "http://localhost:8081",
                "http://localhost:8083",
                "http://localhost:63342"));
        corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
        //允许cookie
        corsConfiguration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return urlBasedCorsConfigurationSource;
    }
}
